﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace System.Peppers.Win32
{
    /// <summary>
    /// Class for handling power states of the system's monitor
    /// *NOTE: all functions can throw Win32Exception on error
    /// </summary>
    public static class MonitorPower
    {
        private const int WM_SYSCOMMAND = 0x0112,
            HWND_BROADCAST = 0xFFFF;
        private static readonly IntPtr SC_MONITORPOWER = new IntPtr(0xF170);
        private static BSM_RECIPIENT _recipient = BSM_RECIPIENT.BSM_APPLICATIONS;

        private enum MONITOR_STATE : int
        {
            OFF = 2,
            STANDBY = 1,
            ON = -1,
        }

        /// <summary>
        /// Turns all monitors on
        /// </summary>
        public static void On()
        {
            if (!User32.BroadcastSystemMessage(BSF_FLAGS.BSF_FORCEIFHUNG, ref _recipient, WM_SYSCOMMAND, SC_MONITORPOWER, new IntPtr((int)MONITOR_STATE.ON)))
            {
                throw new Win32Exception();
            }
        }

        /// <summary>
        /// Turns all monitors off
        /// </summary>
        public static void Off()
        {
            if (!User32.BroadcastSystemMessage(BSF_FLAGS.BSF_FORCEIFHUNG, ref _recipient, WM_SYSCOMMAND, SC_MONITORPOWER, new IntPtr((int)MONITOR_STATE.OFF)))
            {
                throw new Win32Exception();
            }
        }

        /// <summary>
        /// Turns all monitors to stand-by
        /// </summary>
        public static void Standby()
        {
            if (!User32.BroadcastSystemMessage(BSF_FLAGS.BSF_FORCEIFHUNG, ref _recipient, WM_SYSCOMMAND, SC_MONITORPOWER, new IntPtr((int)MONITOR_STATE.STANDBY)))
            {
                throw new Win32Exception();
            }
        }

        /// <summary>
        /// Sets a powerstate for the application, make sure to set it back to normal when the application exits
        /// </summary>
        /// <param name="powerState">Power state enumeration</param>
        public static void SetPowerState(MonitorPowerState powerState)
        {
            if (Kernel32.SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | (EXECUTION_STATE)powerState) == EXECUTION_STATE.NULL)
            {
                throw new Win32Exception();
            }
        }
    }
}
